#ifndef _FNT_CACHE_THREAD_H_
#define _FNT_CACHE_THREAD_H_

#include <QThread>

struct CacheThreadPriv;

struct CacheFile;
class CacheFileRef {
	friend struct CacheThreadPriv;

	CacheFile* _file;

	CacheFileRef(const CacheFileRef& l) =delete;
	CacheFileRef& operator=(const CacheFileRef& l) =delete;

	CacheFileRef(CacheFile* f); // called when locked

	CacheFile* operator->() const { return _file; }

	public:

	CacheFileRef(): _file{nullptr} { }
	~CacheFileRef() {
		release();
	}

	CacheFileRef(CacheFileRef&& r):
		_file{r._file}
	{
		r._file=nullptr;
	}
	CacheFileRef& operator=(CacheFileRef&& r) {
		std::swap(_file, r._file);
		return *this;
	}

	void release();

	bool operator!() const { return !_file; }
	operator bool() const { return _file; }

	bool isReady() const;
	const std::vector<char*>* buffers() const;
	size_t size() const;
};

class CacheThread: public QThread {
	Q_OBJECT;
	friend struct CacheThreadPriv;
	CacheThreadPriv*const priv;

	static CacheThread* _instance;

	void run() override;

	CacheThread();

Q_SIGNALS:
	void threadWarning(const QString& msg);
	void threadError(const QString& msg);
	void requestLogin(const QString& url, const QString& oldusr, const QString& oldpwd);

	public:
	static CacheThread* instance() {
		if(!_instance)
			_instance=new CacheThread{};
		return _instance;
	}
	~CacheThread();

	void stop();

	CacheFileRef download(const QUrl& url);
	void downloadIfIdle(const QUrl& url);

	size_t waitForFile(const CacheFileRef& filesToWait) const;
	size_t waitForFiles(const std::vector<CacheFileRef>& filesToWait) const;

	void updateLogin(const QString& usr, const QString& pwd, bool cancelled);
};

#endif
